#coding=UTF-8 
import sys
reload(sys)
sys.setdefaultencoding('utf8')

from Log import LogD
from ServiceControl import getService
from Error import WebPageNotExist
from Functional import translateFileName
import Static
from selenium.webdriver.android.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support.expected_conditions import title_contains
from selenium.webdriver.support import expected_conditions


def getBrowser():
    return getService( 'browser' )



class Dialog( type ):
    def __new__( cls, name, webpage, bases = (), d = {} ):
        return type.__new__( cls, name, bases, d )

    def __init__( cls, name, webpage, bases = (), d = {} ):
        cls.webpage = webpage
        super( Dialog, cls ).__init__( name, bases, d )

    def getBrowser( cls ):
        browser = getBrowser()
        return browser

    @property
    def browser( cls ):
        return cls.getBrowser()

    @property
    def exist( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        try:
            alert = cls.browser.switch_to_alert()
            t = alert.text
        except Exception, e:
            return False
        return True

    @property
    def text( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        try:
            alert = cls.browser.switch_to_alert()
            return alert.text
        except Exception, e:
            return None

    @text.setter
    def text( cls, value ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        try:
            alert = cls.browser.switch_to_alert()
            alert.send_keys( value )
        except Exception, e:
            pass

    def dismiss( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        try:
            alert = cls.browser.switch_to_alert()
            alert.dismiss()
            import time
            time.sleep( 1 )
        except Exception, e:
            pass

    def accept( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        try:
            alert = cls.browser.switch_to_alert()
            alert.accept()
            import time
            time.sleep( 1 )
        except Exception, e:
            pass


class Frame( type ):
    def __new__( cls, name, findByWhat, findByValue, webpage, frame, bases = (), d = {} ):
        return type.__new__( cls, name, bases, d )

    def __init__( cls, name, findByWhat, findByValue, webpage, frame, bases = (), d = {} ):
        cls.findByWhat = findByWhat
        cls.findByValue = findByValue
        cls.webpage = webpage
        cls.frame = frame
        super( Frame, cls ).__init__( name, bases, d )

    def getBrowser( cls ):
        return getBrowser()

    @property
    def browser( cls ):
        return cls.getBrowser()

    def _switchToFrame( cls ):
        if cls.frame != None:
            cls.frame.activate()
        elif cls.webpage != None:
            cls.webpage.activate()

        if cls.findByWhat == "name":
            cls.browser.switch_to_frame( cls.findByValue )
        elif cls.findByWhat == "index":
            cls.browser.switch_to_frame( int( cls.findByValue ) )

    def activate( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        cls.browser.switch_to_default_content()
        cls._switchToFrame()

    def refresh( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        cls.activate()
        cls.browser.refresh()

    def back( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        cls.activate()
        cls.browser.back()

    def forward( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        cls.activate()
        cls.browser.forward()

    def capture( cls, filename ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        cls.activate()
        return cls.browser.save_screenshot( translateFileName( filename ) )

    def close( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        cls.activate()
        cls.browser.close()

class WebPage( type ):
    def __new__( cls, name, findByWhat, findByValue, bases = (), d = {} ):
        return type.__new__( cls, name, bases, d )

    def __init__( cls, name, findByWhat, findByValue , bases = (), d = {} ):
        cls.findByWhat = findByWhat
        cls.findByValue = findByValue
        super( WebPage, cls ).__init__( name, bases, d )

    def getBrowser( cls ):
        return getBrowser()

    @property
    def browser( cls ):
        return cls.getBrowser()

    @property
    def title( cls ):
        cls.activate()
        return cls.browser.title

    @property
    def isActived( cls ):
        if cls.findByWhat == "title" and  cls.findByValue == cls.browser.title:
            return True
        elif cls.findByWhat == "title" and  cls.findByValue != "" and cls.findByValue in cls.browser.title:
            return True
        #ToDo: add condition find by name
        return False

    @property
    def exist( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        browser = cls.browser
        originalHandle = browser.current_window_handle
        allHandles = browser.window_handles
        
        result = False
        for handle in allHandles:
            browser.switch_to_window( handle )
            if  cls.findByWhat == "title" and cls.findByValue == browser.title:
                result = True
                break
            elif  cls.findByWhat == "title" and cls.findByValue != "" and cls.findByValue in browser.title:
                return True
                break
            #ToDo: add condition find by name
        browser.switch_to_window( originalHandle )
        return result

    def _switchToPage( cls ):
        browser = cls.browser
        originalHandle = browser.current_window_handle
        allHandles = browser.window_handles
#         WebDriverWait(browser, 5,0.5).until(title_contains(cls.findByValue))
        for handle in allHandles:
            browser.switch_to_window( handle )
            if  cls.findByWhat == "title" and cls.findByValue == browser.title:
                return
            elif cls.findByWhat == "title" and cls.findByValue != "" and cls.findByValue in browser.title:
                return
            #ToDo: add condition find by name
        #这个地方我要好好想想， By xuqiang  ^.^
        browser.switch_to_window( originalHandle )
        return
        raise WebPageNotExist()

    def activate( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        if cls.isActived:
            return
        else:
            cls._switchToPage()

    def refresh( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        cls.activate()
        cls.browser.refresh()

    def back( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        cls.activate()
        cls.browser.back()

    def forward( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        cls.activate()
        cls.browser.forward()

    def capture( cls, filename ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        cls.activate()
        return cls.browser.save_screenshot( translateFileName( filename ) )

    def close( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        cls.activate()
        cls.browser.close()

    def windows( cls,name ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        browser = cls.browser
        allHandles = browser.window_handles
        result = False
        for handle in allHandles:
            browser.switch_to_window( handle )
            if  name in browser.title:
                result = True
                break
        return result
    
    def windowClose( cls,name ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        browser = cls.browser
        allHandles = browser.window_handles
        for handle in allHandles:
            browser.switch_to_window( handle )
            if  name in browser.title:
                browser.close()
                break

    
    
class WebElement( type ):
    def __new__( cls, name, findByWhat, findByValue, webpage, frame, bases = (), d = {} ):
        return type.__new__( cls, name, bases, d )

    def __init__( cls, name, findByWhat, findByValue , webpage, frame, bases = (), d = {} ):
        cls.findByWhat = findByWhat
        cls.findByValue = findByValue
        cls.webpage = webpage
        cls.frame = frame
        super( WebElement, cls ).__init__( name, bases, d )

    def getBrowser( cls ):
        browser = getBrowser()
        if cls.frame != None:
            cls.frame.activate()
        elif cls.webpage != None:
            cls.webpage.activate()
        return browser

    @property
    def browser( cls ):
        return cls.getBrowser()

    def getWebElement( cls ):
        return cls.getBrowser().find_element( cls.findByWhat, cls.findByValue )

    @property
    def element( cls ):
        return cls.getWebElement()

    @property
    def isEnabled( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        return element.is_enabled()

    @property
    def exist( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        try:
            cls.getWebElement()
        except Exception, e:
            return False
        return True

    @property
    def text( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        return cls.element.text

class Div( WebElement ):
    pass

class ComboBox( WebElement ):
    def __new__( cls, name, findByWhat, findByValue, webpage, frame, parameter, bases = (), d = {} ):
        return type.__new__( cls, name, bases, d )

    def __init__( cls, name, findByWhat, findByValue, webpage, frame, parameter, bases = (), d = {} ):
        cls.parameter = parameter
        WebElement.__init__( cls, name, findByWhat, findByValue, webpage, frame, bases, d )

    def select( cls, option = None, text = None, index = -1 ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        from selenium.webdriver.support.select import Select
        selecter = Select( element )
        if option != None:
            selecter.select_by_value( option )
        elif index != -1:
            selecter.select_by_index( index )
        elif text != None:
            optionElements = cls.element.find_elements_by_tag_name( "option" )
            for element in optionElements:
                if element.text == text:
                    selecter.select_by_value( element.get_attribute( "value" ) )
                    return
            raise Exception( "No selectable options with text %s found." % text )
        else:
            pass

    @property
    def options( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        optionElements = cls.element.find_elements_by_tag_name( "option" )
        result = []
        for element in optionElements:
            result.append( element.get_attribute( "value" ) )
        return result
    
    @property
    def texts( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        optionElements = cls.element.find_elements_by_tag_name( "option" )
        result = []
        for element in optionElements:
            result.append( element.get_attribute( "value" ) )
            result.append( element.text )
        return result
    
    @property
    def selected( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        return element.get_attribute( "value" )

    @property
    def text( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        value = cls.selected
        optionElements = cls.element.find_elements_by_tag_name( "option" )
        for element in optionElements:
            if element.get_attribute( "value" ) == value:
                return element.text

class ListBox( ComboBox ):
    def deselect( cls, value = None, index = -1 ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        from selenium.webdriver.support.select import Select
        selecter = Select( element )
        if index != -1:
            selecter.deselect_by_index( index )
        elif value != None:
            selecter.deselect_by_value( value )
        else:
            selecter.deselect_all()

    @property
    def selected( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        return element.get_attribute( "value" ).split()

    @property
    def text( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        values = cls.selected
        result = []
        optionElements = cls.element.find_elements_by_tag_name( "option" )
        for element in optionElements:
            elementValue = element.get_attribute( "value" )
            for value in values:
                if elementValue == value:
                    result.append( element.text )
        return result


class StaticLable( WebElement ):
    @property
    def text( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        return element.text


class Editor( WebElement ):
    @property
    def text( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        return element.get_attribute( "value" )
    @text.setter
    def text( cls, value ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        element.clear()
        element.send_keys( value )

    @property
    def isEnabled( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        return element.is_enabled()

class Button( WebElement ):
    def click( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )

#         element = WebDriverWait(cls.browser, 20,0.5).until(EC.element_to_be_clickable((cls.findByWhat,cls.findByValue)))
        element = cls.element
        if not element.is_displayed():
            import selenium
            element.send_keys( selenium.webdriver.common.keys.Keys.ENTER )
        else:
            element.click()

    @property
    def isEnabled( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        return element.is_enabled()

    @property
    def text( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        return element.text
#         return element.get_attribute( "value" )
       

class Table( Button ):
    def click( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        if not element.is_displayed():
            pass
        else:
            import selenium
            if isinstance( cls.browser, selenium.webdriver.Ie ):
                cls.element.send_keys( "selenium.webdriver.common.keys.Keys.ENTER" )
            element.click()

    @property
    def text( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        return cls.element.text

    def getStatusCell(cls,lineIndex,columnIndex):
        try:
            rows = cls.element.find_elements("xpath",".//tbody/tr")
            lines = rows[lineIndex].find_elements("xpath",".//td")
            cell = lines[columnIndex]
#             row = cls.element.find_element("xpath",".//tbody/tr[0]/td[8]/div[1]/span[1]")
#             find_elements("xpath",'//*[@id="' + self.table_id +'"]/tbody/tr') 
            if cell ==None:
                return None
            else:
                return cell.text
#             if len(rows)< lineIndex:
#                 return None 
#             host = rows[lineIndex].find_element("xpath",'//td['+str(columnIndex)+']/div[1]/span[1]')  
#             if host == None:
#                 return None
#             else:
#                 return host.text
        except Exception,e:
            print "getStatusCell exception. line is " + str(lineIndex) + ",column is " + str(columnIndex)
            return None
    
    def getCell(cls,lineIndex,columnIndex):
        try:
            rows = cls.element.find_elements("xpath",".//tbody/tr")
            lines = rows[lineIndex].find_elements("xpath",".//td")
            cell = lines[columnIndex]
            if cell ==None:
                return None
            else:
                return cell

        except Exception,e:
            print "getCell exception. line is " + str(lineIndex) + ",column is " + str(columnIndex)
            print e
            return None
    
    def getHeads(cls):
        heads = cls.element.find_elements("xpath",".//thead/tr/th") 
#         find_elements("xpath",'//*[@id="' + self.table_id +'"]/thead/tr/th')
        headText = []
        for head in heads:
            headText.append(head.text)
        return headText
    
    def getRows(cls):
        try:
            rows = cls.element.find_elements("xpath",".//tbody/tr")
            return rows
        except Exception,e:
            print e
            return None
        
    
class RadioButton( Button ):
    def check( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        cls.element.click()

    @property
    def isChecked( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        return element.is_selected()


class CheckBox( WebElement ):
    def check( cls , checked = True ):
        if isinstance( checked, str ) and checked.upper() == "FALSE":
            return cls.uncheck()
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        if element == None:
            return
        if element.is_selected():
            return
        else:
            element.click()

    def uncheck( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        if element == None:
            return
        if element.is_selected():
            element.click()
        else:
            return
    @property
    def isChecked( cls ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        element = cls.element
        return element.is_selected()


class OpenFileDialog( WebElement ):
    def open( cls, filename ):
        LogD.write( cls.__name__ + '.' + sys._getframe().f_code.co_name + ' begin' )
        import os
        if  os.access( filename, os.F_OK ):
            file = os.path.abspath( filename )
        else:
            import Static
            filename = Static.WebTestDir + '\\input\\' + filename
            if not os.access( filename, os.F_OK ):
                raise Exception( "no file: %s found!" % filename )
        cls.element.send_keys( filename )


class Slider( WebElement ):
    pass
